package org.daochong.spring;

import java.util.Map;

import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;

public class DefaultSpringBeanLoader
		implements SpringBeanLoader, BeanNameAware, ApplicationListener<ContextRefreshedEvent> {

	private String proxyBeanClass;

	private String beanName;

	private Map<String, Object> props;

	public Map<String, Object> getProps() {
		return props;
	}

	public String getProxyBeanClass() {
		return proxyBeanClass;
	}

	public void setProxyBeanClass(String proxyBeanClass) {
		this.proxyBeanClass = proxyBeanClass;
	}

	public void setProps(Map<String, Object> props) {
		this.props = props;
	}

	public String getBeanName() {
		return beanName;
	}

	public void setBeanName(String beanName) {
		this.beanName = beanName;
	}

	protected String getProxyClass() {
		return this.proxyBeanClass;
	}

	protected void setProperty(ApplicationContext context, BeanDefinitionBuilder builder, BeanDefinition bd,
			String beanName) {

	}

	public void load(ApplicationContext context) {
		BeanDefinitionBuilder builder;
		if (context.getParent() == null) {
			builder = BeanDefinitionBuilder.rootBeanDefinition(getProxyClass());
			ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) context;
			BeanDefinitionRegistry beanDefinitonRegistry = (BeanDefinitionRegistry) configurableApplicationContext
					.getBeanFactory();
			BeanDefinition bd = beanDefinitonRegistry.getBeanDefinition(getBeanName());
			PropertyValue pv = bd.getPropertyValues().getPropertyValue("props");
			if (pv != null) {
				ManagedMap<?, ?> m = (ManagedMap<?, ?>) pv.getValue();
				for (Object key : m.keySet()) {
					if (key instanceof TypedStringValue) {
						TypedStringValue o = (TypedStringValue) key;
						String prop = o.getValue();
						Object obj = m.get(key);
						if (obj instanceof BeanReference) {
							BeanReference br = (BeanReference) obj;
							builder.addPropertyReference(prop, br.getBeanName());
						} else {
							builder.addPropertyValue(prop, obj);
						}
					}
				}
			}
			setProperty(context, builder, bd, getBeanName());
			beanDefinitonRegistry.registerBeanDefinition(getBeanName(), builder.getBeanDefinition());
		}
	}

	public void onApplicationEvent(ContextRefreshedEvent event) {
		load(event.getApplicationContext());
	}

}
